package interpreter.biback.domain

import biback.domain.price.{BaseInt, IntKey, IntPrice}
import biback.domain.product._
import biback.domain.{ProductCode, TrnDate}
import cats.Monad
import cats.data.NonEmptyList

trait ProductMock[F[_]] {
  val product2params: Map[BaseProduct, ProductParam]
  val products: List[SaleableProduct]
  val baseInts: List[BaseInt]
  val intPrices: List[IntPrice]
  val productIn = new ProductAlgebra.Service[F] {
    override def get(prdCode: ProductCode)(implicit F: Monad[F]): ErrOrF[Option[SaleableProduct]] =
        resultF(products.find(_.code == prdCode))
    override def getParam(product: BaseProduct)(implicit F: Monad[F]): ErrOrF[Option[ProductParam]] =
      resultF(product2params.get(product))
    override def foundIntPrice(prdCode: ProductCode)(implicit F: Monad[F]): ErrOrF[IntPrice] =
      for {
        p <- foundO(products.find(_.code == prdCode), SaleableProductNotFound(prdCode))
        i <- foundO(intPrices.find(_.no == p.intNo), InterestNotFound(p.intNo))
      } yield i
    override def listBaseInt(key: IntKey, from: TrnDate, to: TrnDate)(implicit F: Monad[F]): ErrOrF[NonEmptyList[BaseInt]] = {
      val sorted = baseInts.sortBy(_.effectiveDate)
      val (pre, gt) = sorted.span(_.effectiveDate <= from)
      val (post, _) = gt.span(_.effectiveDate < to)
      for {
        b <- orF(pre.nonEmpty, pre.takeRight(1) ++ post, CalcIntNotFound(from, to))
      } yield NonEmptyList.ofInitLast(b.dropRight(1), b.last)
    }
  }
}